﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using SchEdu.Framework.DataModel;
using SchEdu.Framework.Algorithm;
using SchEdu.Framework.Objective;
using SchEdu.Framework.Logging;


namespace SchEduApp
{
    public partial class MDIParentSchEdu : Form
    {
        EnvironmentForm environmentForm = null;
        OrderForm orderForm = null;
        DependencyForm dependencyForm = null;
        SolutionForm solutionForm = null;
        SetupTimeForm setupTimeForm = null;
        AlgorithmForm algorithmForm = null;

        string fileName = string.Empty;
        ObjectiveList objectives = new ObjectiveList();

        public MDIParentSchEdu()
        {
            InitializeComponent();
            Initialize();

        }

        private void Initialize()
        {
            LoadAlgorithms();
            LoadObjectives();
        }

        #region Load Menus
        private void LoadAlgorithms()
        {
            AlgorithmConfigurationSection algorithmConfigurationSection =
                ConfigurationManager.GetSection("algorithmConfigurationSection")
                as AlgorithmConfigurationSection;
            BuidAlgorithmMenuItem(algorithmMenu, algorithmConfigurationSection.AlgorithmMenuItems);
        }

        private void LoadObjectives()
        {
            ObjectiveConfigurationSection objectiveConfigurationSection =
                ConfigurationManager.GetSection("objectiveConfigurationSection")
                as ObjectiveConfigurationSection;

            foreach (ObjectiveItem item in objectiveConfigurationSection.ObjectiveItems)
            {
                objectives.Add(LoadObjectiveAssembly(item));
            }

        }

        private void BuidAlgorithmMenuItem(ToolStripMenuItem parentMenu, AlgorithmMenuItemCollection algorithmMenuItems)
        {
            foreach (AlgorithmMenuItem item in algorithmMenuItems)
            {
                if (item.AlgorithmMenuItems.Count == 0)
                {
                    ToolStripAlgorithmMenuItem menuItem = new ToolStripAlgorithmMenuItem();
                    menuItem.Text = item.Name;
                    menuItem.Algorithm = LoadAlgorithmAssembly(item.Assembly, item.Class);
                    menuItem.Click +=new EventHandler(algorithmMenuItem_Click);
                    parentMenu.DropDownItems.Add(menuItem);
                }
                else
                {
                    ToolStripAlgorithmMenuItem menuItem = new ToolStripAlgorithmMenuItem();
                    menuItem.Text = item.Name;
                    parentMenu.DropDownItems.Add(menuItem);
                    BuidAlgorithmMenuItem(menuItem, item.AlgorithmMenuItems);
                }
            }
        }

        private IAlgorithm LoadAlgorithmAssembly(string algorithmAssembly, string algorithmClass)
        {
                Assembly assembly;
                assembly = Assembly.Load(algorithmAssembly);
                Type algorithmType = assembly.GetType(algorithmClass);
                IAlgorithm algorithm =
                    (IAlgorithm)System.Activator.CreateInstance(algorithmType);
                SchEduAppContext.AlgorithmList.Add(algorithm);
                return algorithm;
        }
        #endregion


        private IObjective LoadObjectiveAssembly(ObjectiveItem objectiveItem)
        {
            Assembly assembly;
            assembly = Assembly.Load(objectiveItem.Assembly);
            Type objectiveType = assembly.GetType(objectiveItem.Class);
            IObjective objective =
                (IObjective)System.Activator.CreateInstance(objectiveType);
            SchEduAppContext.ObjectiveList.Add(objective);
            return objective;
        }

        void algorithmMenuItem_Click(object sender, EventArgs e)
        {
            ToolStripAlgorithmMenuItem menuItem = sender as ToolStripAlgorithmMenuItem;
            if (menuItem == null)
            {
                return;
            }

            SchEduDataSet.SolutionRow solution;
            try
            {
                solution = RunAlgorithm(menuItem.Algorithm);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SchEdu Algorithm Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                RunObjectives(solution);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SchEdu Objective Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            GanttForm ganttForm = new GanttForm();
            ganttForm.Solution = solution;
            ganttForm.MdiParent = this;
            ganttForm.Show();

        }

        private SchEduDataSet.SolutionRow RunAlgorithm(IAlgorithm algorithm)
        {
            algorithm.SchEduData = SchEduAppContext.SchEduData;
            return algorithm.Run();
        }

        private void RunObjectives(SchEduDataSet.SolutionRow solution)
        {
            Performancer performancer = new Performancer(SchEduAppContext.SchEduData, solution, objectives);
            performancer.Generate();
        }


        private void ShowNewForm(object sender, EventArgs e)
        {
            SchEduAppContext.SchEduData = new SchEduData();
            CloseAllToolStripMenuItem_Click(null, null);
            EnableAllWindow();
        }


        private void OpenFile(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            openFileDialog.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                fileName = openFileDialog.FileName;
                OpenSchedule();
            }
            
        }

        private void SaveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            saveFileDialog.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                fileName = saveFileDialog.FileName;
                SaveSchedulingData();
            }
        }

        void SaveSchedulingData()
        {
            System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SchEduData));
            System.IO.StreamWriter stream = new System.IO.StreamWriter(fileName);
            xmlSerializer.Serialize(stream, SchEduAppContext.SchEduData);
            stream.Close();
        }

        void OpenSchedule()
        {
            System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(SchEduData));
            System.IO.StreamReader stream = new System.IO.StreamReader(fileName);
            SchEduAppContext.SchEduData = (SchEduData)xmlSerializer.Deserialize(stream);
            stream.Close();
            CloseAllToolStripMenuItem_Click(null, null);
            EnableAllWindow();

        }

        private void ExitToolsStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }


        private void CascadeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.Cascade);
        }

        private void TileVerticalToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileVertical);
        }

        private void TileHorizontalToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileHorizontal);
        }

        private void ArrangeIconsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.ArrangeIcons);
        }

        private void CloseAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Form childForm in MdiChildren)
            {
                childForm.Close();
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (fileName == string.Empty)
            {
                SaveAsToolStripMenuItem_Click(null, null);
            }
            else
            {
                SaveSchedulingData();
            }
        }

        private void saveToolStripButton_Click(object sender, EventArgs e)
        {
            if (fileName == string.Empty)
            {
                SaveAsToolStripMenuItem_Click(null, null);
            }
            else
            {
                SaveSchedulingData();
            }
        }

        private void EnableAllWindow()
        {
            EnableEnvironmentWindow();
            EnableOrderWindow();
            EnableDependencyWindow();
            EnableSetupTimeWindow();
        }

        private void EnableEnvironmentWindow()
        {
            environmentForm = new EnvironmentForm();
            environmentForm.MdiParent = this;
            environmentForm.Show();
        }

        private void EnableOrderWindow()
        {
            orderForm = new OrderForm();
            orderForm.MdiParent = this;
            orderForm.Show();
        }

        private void EnableDependencyWindow()
        {
            dependencyForm = new DependencyForm();
            dependencyForm.MdiParent = this;
            dependencyForm.Show();
        }

        private void EnableSolutionWindow()
        {
            solutionForm = new SolutionForm();
            solutionForm.MdiParent = this;
            solutionForm.Show();
        }


        private void EnableAlgorithmWindow()
        {
            algorithmForm = new AlgorithmForm();
            algorithmForm.MdiParent = this;
            algorithmForm.Show();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutForm aboutForm = new AboutForm();
            AboutInfo aboutInfo = new AboutInfo();
            aboutForm.SetAboutInfo(aboutInfo);
            aboutForm.ShowDialog();
        }

        private void ordersToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EnableOrderWindow();
        }

        private void enrivomentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EnableEnvironmentWindow();
        }

        private void dependenciesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EnableDependencyWindow();
        }

        private void solutionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EnableSolutionWindow();
        }

        private void generatorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GeneratorForm generatorForm = new GeneratorForm();
            generatorForm.ShowDialog();
            CloseAllToolStripMenuItem_Click(null, null);
            EnableAllWindow();
        }

        private void setupTimeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EnableSetupTimeWindow();
        }

        private void EnableSetupTimeWindow()
        {
            setupTimeForm = new SetupTimeForm();
            setupTimeForm.MdiParent = this;
            setupTimeForm.Show();
        }

        private void algorithmsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EnableAlgorithmWindow();
        }

    }

    public static class SchEduAppContext
    {
        private static SchEduData schEduData = new SchEduData();

        public static SchEduData SchEduData
        {
            get { return schEduData; }
            set { schEduData = value; }
        }

        private static AlgorithmList algorithmList = new AlgorithmList();

        public static AlgorithmList AlgorithmList
        {
            get { return algorithmList; }
            set { algorithmList = value; }
        }

        private static ObjectiveList objectiveList = new ObjectiveList();

        public static ObjectiveList ObjectiveList
        {
            get { return objectiveList; }
            set { objectiveList = value; }
        }


    }


    class ToolStripAlgorithmMenuItem : ToolStripMenuItem
    {
        IAlgorithm algorithm;

        public IAlgorithm Algorithm
        {
            get { return algorithm; }
            set { algorithm = value; }
        }


    }
}
